#pragma once
#include <unordered_map>
#include <list>
#include <filesystem>
#include <vector>
#include <utility>
#if defined(__linux__)
#include <sys/uio.h>
#endif
#include <cstring>
#include <string_view>
#include <any>
#if defined(__linux__)
#include "linux_pb/frpc.pb.h"
#endif
#if defined(_WIN32)
#include "win_pb/frpc.pb.h"
#include "win_pb/rpc_meta_brpc.pb.h"
#endif

#include "status_code.h"
#include <cppbase/logging.h>
#include <workflow/PlatformSocket.h>
#include <vector>
#define FRPC_START_BYTES "PRPC"

namespace frpc
{
#if defined(_WIN32)
	/*
	struct iovec {
		void* iov_base;
		size_t iov_len;
	};
	*/
#endif

	class Msg
	{
	public:
#pragma pack(push, 4)
		struct Head
		{
			/*
			uint16_t start_bytes ; //每个msg的起始8字节，用于标识协议
			Command cmd;
			private:
			uint32_t _length;//flowing bytes size without head
			public:
			uint16_t request_seq;
			//uint8_t reply_seq; use meta if chunked or compress
			void set_meta_bit(){_length|=0x80000000;}//set highest bit
			void clear_meta_bit(){_length&=0x7FFFFFFF;}//set highest bit
			uint32_t content_length(){return  _length&0x7FFFFFFF;}
			void set_content_length(uint32_t v){if(_length&0x80000000) {v|=0x80000000 ;_length=v;}else _length=v; }
			bool has_meta(){return _length&0x80000000;}// 2 bytes at begin of content is meta length
			*/


			char start_bytes[4];
		private:
			uint32_t full_size;//real body size + attachment size
			uint32_t meta_size;
		public:
			uint32_t get_metasize() { return ntohl(meta_size); }
			void set_metasize(uint32_t size) { meta_size  = htonl(uint32_t(size)); }
			uint32_t get_fullsize() { return ntohl(full_size); }
			void set_fullsize(uint32_t size) { full_size = htonl(uint32_t(size)); }

		};
#pragma pack(pop)
	protected:


		
		struct iovec headmeta_buf;//head 和meta 共用一个buff
		//int headmeta_used;
		struct iovec body_buf;
		int body_used;
		std::vector<struct iovec> _attachment;

		
		//   uint16_t meta_size(){return *(uint16_t*)((char*)headcontent_buf.iov_base+sizeof(Head));}
	public:
		BrpcMeta meta;
		enum class ParseStage {
			Init = 0,
			HeadDone = 1,
			WaitMeta = 2,
			MetaDone = 3,
			WaitBody = 4,
			WaitAttachment = 6,
			PacketDone = 10,
			Failed = -1
		};
		Msg()
		{

			headmeta_buf.iov_len = 120;
			//headmeta_used=sizeof(Head);
			headmeta_buf.iov_base = malloc(headmeta_buf.iov_len);
			memset(&body_buf, 0, sizeof(struct iovec));
			body_used = 0;
			memcpy(head()->start_bytes, FRPC_START_BYTES, 4);
		}
		Head* head() { return (Head*)headmeta_buf.iov_base; };
		void set_head(Head& h) { *head() = h; }
		int need_size() {
			return head()->get_fullsize() - meta.ByteSizeLong() - body_used - attachment_used();
		}
		//   int head_size(){return sizeof(Head);}
		ParseStage parse_stage = ParseStage::Init;
		int parse_full_stream(char* buf, size_t* size);
		std::string_view body() { return std::string_view((char*)body_buf.iov_base, body_used); };
		void reserve_body_buf(int size)
		{
			if (size <= body_buf.iov_len)
				return;
			body_buf.iov_len = size;
			if (body_buf.iov_base)
			{
				auto r = realloc(body_buf.iov_base, size);
				if (!r) {
					FATAL("allocate memory failed.");
				}
				body_buf.iov_base = r;
			}
			else
				body_buf.iov_base = malloc(size);
			if (!body_buf.iov_base)
			{
				FATAL("allocate memory failed.");

			}

		};
		void append_body_copy(char* buf, int size);

		bool bad_input();

		//read write content data
		void set_output(std::string&& s) {};

		// void set_status_output(Status v,char* buf){set_output(buf,strlen(buf));set_status(v);};
		//void set_ok_output(std::string&& s = std::string());
		//void set_ok_output(uint16_t);
		//void set_ok_output(uint32_t);
		//void set_ok_output(uint16_t, uint16_t);
		// void set_cmd_output(Command cmd,std::string &&s = std::string());
		//void set_bad_output(Status code, std::string&& s = std::string());
		void add_attachment_nocopy(void* buf, size_t size);
		// void set_cmd(Command cmd){head()->cmd=cmd;}
		 // void set_output_copy(char *, int size);

		//  uint32_t output_length() { return headcontent_buf.iov_len; };
		int attachment_used() {
			int size = 0;
			for (auto& i : _attachment) {
				size += i.iov_len;
			}
			return size;
		}
		std::vector<struct iovec> take_attachment() { std::vector<struct iovec> v; std::swap(v, _attachment);  return v; };

		int collect_output(struct iovec iov[])
		{
			int meta_size = meta.ByteSizeLong();
			head()->set_metasize(meta_size);
			if (headmeta_buf.iov_len < meta_size + sizeof(Head)) {
				auto r = realloc(headmeta_buf.iov_base, meta_size + sizeof(Head));
				if (!r) {
					FATAL("Failed to reallocate memory");
				}
				headmeta_buf.iov_base = r;
			}
			if (meta.SerializeToArray((char*)headmeta_buf.iov_base + sizeof(Head), meta_size) == false) {
				LOG("Failed toserilize meta");
			};
			iov[0].iov_base = headmeta_buf.iov_base;
			iov[0].iov_len = meta_size + sizeof(Head);

			int cnt = 1;


			if (body_used > 0) {
				iov[cnt].iov_base = body_buf.iov_base;
				iov[cnt++].iov_len = body_used;
			}
			int fullsize = body_used + meta_size;
			for (auto& i : _attachment) {
				iov[cnt++] = i;
				fullsize += i.iov_len;//rpc协议中，head部分的bodysize=pb的body字节数+附件字节数
			}
			head()->set_fullsize(fullsize);


			return cnt;
		};

		~Msg()
		{
			//DLOG("cmd:0x%X,user seq:%d,call ~Msg",uint16_t(head()->cmd),head()->request_seq);
			free(headmeta_buf.iov_base);
			free(body_buf.iov_base);
			for (auto& i : _attachment) {
				free(i.iov_base);
			}
		}
	};


}
